//
//  PostViewController.m
//  Buzz API Demo
//
//  Created by Peter Hopkins on 5/7/10.
//  Copyright 2010 Google Inc. All rights reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

#import "PostDetailViewController.h"

#import "BuzzDao.h"

#import "Author.h"
#import "Comment.h"
#import "PhotoAttachment.h"
#import "Post.h"

#import "LikersViewController.h"
#import "NewPostViewController.h"

#import <QuartzCore/QuartzCore.h>


#define kAttachmentCellHeight 160


@interface PostDetailViewController ()
- (UITableViewCell *)tableView:(UITableView *)tableView
      contentSectionCellForRow:(NSUInteger)row;
- (NSManagedObjectID *)commentKeyForRow:(NSInteger)row;
- (NSUInteger)commentHeightForRow:(NSInteger)row;
- (void)setCommentHeight:(NSUInteger)height forRow:(NSInteger)row;
- (UITableViewCell *)bylineCellForAuthor:(Author *)author date:(NSDate *)date;
@end

@implementation PostDetailViewController

enum Sections {
  kContentSection = 0,
//  kAuthorSection,
//  kLikesSection,
  kCommentsSection,
  NUM_SECTIONS
};

enum ContentSectionRows {
  kContentSectionBylineRow,
  kContentSectionContentRow,
  kContentSectionAttachmentRow,
  kContentSectionVisibilityRow,
  kContentSectionLikersRow,
  NUM_CONTENT_SECTION_ROWS
};

enum CommentsSectionRows {
  NUM_COMMENTS_SECTION_ROWS
};

@synthesize dao = dao_;

- (void)showPost:(Post *)post {
  [currentPost_ removeObserver:self forKeyPath:@"repliesCount"];

  [currentPost_ autorelease];
  currentPost_ = [post retain];

  [postContentTableViewCell_ release];
  postContentTableViewCell_ = nil;

  [attachmentCell_ release];
  attachmentCell_ = nil;
  [attachmentScrollView_ release];
  attachmentScrollView_ = nil;

  [commentHeights_ release];
  commentHeights_ = [[NSMutableDictionary alloc] init];

  [commentCells_ release];
  commentCells_ = [[NSMutableDictionary alloc] init];

  [commentResults_ release];
  commentResults_ = [[dao_ fetchCommentsForPost:post delegate:self] retain];
  [dao_ syncComments:post];

  [self setTitle:[NSString stringWithFormat:@"Buzz from %@", [[post author] name]]];
  [[[self navigationItem] backBarButtonItem] setTitle:@"Buzz"];
  [[self tableView] reloadData];

  [currentPost_ addObserver:self
                 forKeyPath:@"repliesCount"
                    options:NSKeyValueObservingOptionNew
                    context:nil];
}


- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
  if (object == currentPost_) {
    [dao_ syncComments:currentPost_];
    [[self tableView] reloadData];
  }
}


- (NSArray *)comments {
  NSArray *sections = [commentResults_ sections];
  if (![sections count]) {
    return [NSArray array];
  } else {
    id <NSFetchedResultsSectionInfo> sectionInfo = [sections objectAtIndex:0];
    return [sectionInfo objects];
  }
}


#pragma mark ViewController view methods


- (void)viewDidUnload {
  [postContentTableViewCell_ release];
  postContentTableViewCell_ = nil;
}


- (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];

  [commentCells_ release];
  commentCells_ = [[NSMutableDictionary alloc] init];
}


#pragma mark Table view methods

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  return NUM_SECTIONS;
}


- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
  switch (section) {
    case kContentSection:
      return nil;

    case kCommentsSection:
      if ([currentPost_ repliesCount]) {
        return [NSString stringWithFormat:@"%@ Comments", [currentPost_ repliesCount]];
      } else {
        return nil;
      }
  }

  return nil;
}


// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  switch (section) {
    case kContentSection:
      return NUM_CONTENT_SECTION_ROWS;

    case kCommentsSection:
      return [[self comments] count] * 2 + 1;

    default:
      return 0;
  }
}


- (NSManagedObjectID *)commentKeyForRow:(NSInteger)row {
  Comment *comment = [[self comments] objectAtIndex:row];
  return [comment objectID];
}


- (NSUInteger)commentHeightForRow:(NSInteger)row {
  NSNumber *heightNumber = [commentHeights_ objectForKey:[self commentKeyForRow:row]];
  return [heightNumber intValue];
}


- (void)setCommentHeight:(NSUInteger)height forRow:(NSInteger)row {
  [commentHeights_ setObject:[NSNumber numberWithInt:height]
                      forKey:[self commentKeyForRow:row]];
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {    
  switch ([indexPath section]) {
    case kContentSection:
      return [self tableView:tableView contentSectionCellForRow:[indexPath row]];

    case kCommentsSection: {
      int row = [indexPath row] / 2;

      if (row == [[self comments] count]) {
        UITableViewCell *cell = [[self tableView] dequeueReusableCellWithIdentifier:@"PostCommentRow"];
        if (cell == nil) {
          cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                         reuseIdentifier:@"PostCommentRow"] autorelease];
        }

        [[cell textLabel] setText:@"Add a comment…"];

        return cell;
      } else if ([indexPath row] % 2 == 0) {
        Comment *comment = [[self comments] objectAtIndex:row];
        return [self bylineCellForAuthor:[comment author] date:[comment published]];
      } else {
        WebTableViewCell *cell = [commentCells_ objectForKey:[self commentKeyForRow:row]];

        if (cell == nil) {
          Comment *comment = [commentResults_ objectAtIndexPath:[NSIndexPath indexPathForRow:row
                                                                                   inSection:0]];

          cell = [[[WebTableViewCell alloc] initWithReuseIdentifier:nil] autorelease];

          [cell setDelegate:self];
          [cell setUserData:[NSNumber numberWithInt:row]];
          [cell setHTML:[comment contentHTML]];

          [commentCells_ setObject:cell forKey:[self commentKeyForRow:row]];
        }

        return cell;
      }
    }
      
    default:
      return nil;
  }
}


- (UITableViewCell *)bylineCellForAuthor:(Author *)author date:(NSDate *)date {
  UITableViewCell *cell = [[self tableView] dequeueReusableCellWithIdentifier:@"ContentSectionBylineRow"];
  if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
                                   reuseIdentifier:@"ContentSectionBylineRow"] autorelease];
  }
  
  [[cell textLabel] setText:[NSString stringWithFormat:@"%@ wrote…", [author name]]];
  
  NSString *photoURL = [author photoURL];
  if (photoURL) {
    [[cell imageView] setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:photoURL]]]];
    [[cell imageView] setClipsToBounds:YES];
  } else {
    [[cell imageView] setImage:nil];
  }
  
  NSDateFormatter *timeFormatter;
  timeFormatter = [[[NSDateFormatter alloc] init] autorelease];
  [timeFormatter setDateStyle:NSDateFormatterNoStyle];
  [timeFormatter setTimeStyle:NSDateFormatterShortStyle];
  
  NSDateFormatter *dateFormatter;
  dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
  [dateFormatter setDateStyle:NSDateFormatterShortStyle];
  [dateFormatter setTimeStyle:NSDateFormatterNoStyle];
  
  [[cell detailTextLabel] setText:[NSString stringWithFormat:@"%@ on %@",
                                   [timeFormatter stringFromDate:date],
                                   [dateFormatter stringFromDate:date]]];
  return cell;
  
}

- (UITableViewCell *)tableView:(UITableView *)tableView
      contentSectionCellForRow:(NSUInteger)row {
  switch (row) {
    case kContentSectionBylineRow:
      return [self bylineCellForAuthor:[currentPost_ author] date:[currentPost_ updatedDate]];

    case kContentSectionContentRow: {
      if (postContentTableViewCell_ == nil) {
        postContentTableViewCell_ = [[WebTableViewCell alloc] initWithReuseIdentifier:nil];
        [postContentTableViewCell_ setDelegate:self];
        [postContentTableViewCell_ setHTML:[currentPost_ contentHTML]];
      }

      return postContentTableViewCell_;
    }

    case kContentSectionAttachmentRow: {
      if (attachmentCell_ == nil) {
        attachmentCell_ = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                                 reuseIdentifier:nil];
        CGRect cellFrame = CGRectMake(0, 0, 300, kAttachmentCellHeight);
        [attachmentCell_ setFrame:cellFrame];
        [attachmentCell_ setAutoresizesSubviews:NO];

        CGRect scrollFrame = CGRectMake(20, 10, 280, kAttachmentCellHeight - 20);
        attachmentScrollView_ = [[UIScrollView alloc] initWithFrame:scrollFrame];
        [attachmentScrollView_ setShowsVerticalScrollIndicator:NO];
        [attachmentScrollView_ setShowsHorizontalScrollIndicator:NO];

        [attachmentScrollView_ setClipsToBounds:YES];
        [attachmentCell_ addSubview:attachmentScrollView_];

        int x = 0;
        NSEnumerator *attachmentE = [[currentPost_ attachments] objectEnumerator];
        for (int i = 0; i < [[currentPost_ attachments] count]; ++i) {
          PhotoAttachment *attachment = [attachmentE nextObject];

          CGRect photoFrame = CGRectMake(x, 0, 100.0, scrollFrame.size.height);
          UIImageView *photoView = [[[UIImageView alloc] initWithFrame:photoFrame] autorelease];

          [photoView setContentMode:UIViewContentModeScaleAspectFit];
          [photoView setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[attachment previewURL]]]]];
          [photoView setUserInteractionEnabled:YES];
          [attachmentScrollView_ addSubview:photoView];
          x += (100 + 10);
        }

        if (x > 0) {
          x -= 10;
        }

        CGSize attachmentSize = CGSizeMake(x, scrollFrame.size.height);
        [attachmentScrollView_ setContentSize:attachmentSize];

        if (attachmentSize.width < scrollFrame.size.width) {
          scrollFrame.origin.x += (scrollFrame.size.width - attachmentSize.width) / 2;
          [attachmentScrollView_ setFrame:scrollFrame];
        }
      }

      return attachmentCell_;
    }
      
    case kContentSectionVisibilityRow: {
      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ContentSectionVisibilityRow"];
      if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:@"ContentSectionVisibilityRow"] autorelease];
      }

      NSString *text;
      if ([[currentPost_ visibility] count]) {
        text = [[[[currentPost_ visibility] objectEnumerator] nextObject] name];
        if (text == nil) {
          text = @"Private to someone or something";
        }
      } else {
        text = @"Unknown Visibility";
      }

      [[cell textLabel] setText:text];
      [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
      return cell;
    }
      
    case kContentSectionLikersRow: {
      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ContentSectionLikersRow"];
      if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:@"ContentSectionLikersRow"] autorelease];
      }
      
      NSUInteger likersCount = [[currentPost_ likersCount] intValue];

      NSString *text;
      if (likersCount == 0) {
        text = @"No one liked this";
      } else if (likersCount == 1) {
        text = @"One person liked this";
      } else {
        text = [NSString stringWithFormat:@"%d people liked this", likersCount];
      }

      [[cell textLabel] setText:text];
      [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];

      return cell;
    }
      
    default:
      return nil;
  }
}


- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  if ([indexPath section] == kContentSection &&
      [indexPath row] == kContentSectionContentRow) {
    return [postContentTableViewCell_ height];
  }

  if ([indexPath section] == kContentSection &&
      [indexPath row] == kContentSectionAttachmentRow) {
    return [[currentPost_ attachments] count] ? kAttachmentCellHeight : 0;
  }

  if ([indexPath section] == kCommentsSection) {
    int row = [indexPath row];
    if (row % 2 == 1) {
      return [self commentHeightForRow:row / 2];
    }
  }

  return 44;
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  if ([indexPath section] == kCommentsSection && [indexPath row] / 2 == [[self comments] count]) {
    NewPostViewController *controller = [[[NewPostViewController alloc] initWithDao:dao_
                                                                   commentingOnPost:currentPost_] autorelease];
    [self presentModalViewController:controller animated:YES];
  } else if ([indexPath section] == kContentSection && [indexPath row] == kContentSectionLikersRow) {
    LikersViewController *likersController = [[[LikersViewController alloc] initWithDao:dao_ post:currentPost_] autorelease];
    [[self navigationController] pushViewController:likersController animated:YES];
  }

  [tableView deselectRowAtIndexPath:indexPath animated:NO];
}


#pragma mark NSFetchedResultsController delegate


- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
  [[self tableView] beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller
  didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex
     forChangeType:(NSFetchedResultsChangeType)type {
  // ignored
}


- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath
     forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath {
  
  UITableView *tableView = [self tableView];
  
  switch(type) {
      
    case NSFetchedResultsChangeInsert: {
      int row = [newIndexPath row];
      [tableView insertRowsAtIndexPaths:[NSArray arrayWithObjects:[NSIndexPath indexPathForRow:row * 2 inSection:kCommentsSection],
                                         [NSIndexPath indexPathForRow:row * 2 + 1 inSection:kCommentsSection], nil]
                       withRowAnimation:UITableViewRowAnimationFade];
      break;
    }
      
    case NSFetchedResultsChangeDelete: {
      int row = [indexPath row];
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:[NSIndexPath indexPathForRow:row * 2 inSection:kCommentsSection],
                                         [NSIndexPath indexPathForRow:row * 2 + 1 inSection:kCommentsSection], nil]
                       withRowAnimation:UITableViewRowAnimationFade];
      break;
    }
      
    case NSFetchedResultsChangeUpdate:
      break;
      
    case NSFetchedResultsChangeMove:
      break;
  }
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
  [[self tableView] endUpdates];
}



#pragma mark WebTableViewCell delegate

- (BOOL)webTableViewCell:(WebTableViewCell *)cell
shouldStartLoadWithRequest:(NSURLRequest *)request
 navigationType:(UIWebViewNavigationType)navigationType {
  UIWebView *linkView = [[[UIWebView alloc] initWithFrame:[[self view] frame]] autorelease];
  [linkView setScalesPageToFit:YES];
  [linkView loadRequest:request];

  UIViewController *linkViewController = [[[UIViewController alloc] initWithNibName:nil bundle:nil] autorelease];
  [linkViewController setView:linkView];

  [[self navigationController] pushViewController:linkViewController animated:YES];
  return NO;
}


- (void)webTableViewCell:(WebTableViewCell *)cell loadedWithHeight:(NSUInteger)height {
  if (cell != postContentTableViewCell_) {
    NSNumber *rowNumber = [cell userData];

    NSUInteger oldHeight = [self commentHeightForRow:[rowNumber intValue]];
    if (oldHeight == height) {
      return;
    }

    [self setCommentHeight:height forRow:[rowNumber intValue]];
  }

  [[self tableView] beginUpdates];
  [[self tableView] endUpdates];
}


#pragma mark Memory management


- (void)dealloc {
  [currentPost_ removeObserver:self forKeyPath:@"repliesCount"];

  [dao_ release];
  [currentPost_ release];
  [postContentTableViewCell_ release];
  [attachmentCell_ release];
  [attachmentScrollView_ release];
  [commentHeights_ release];
  [commentCells_ release];
  [commentResults_ release];

  [super dealloc];
}


@end

